//
//  MSChainMaker.m
//  MSDemo
//
//  Created by mac on 2021/6/18.
//

#import "MSChainMaker.h"

#define originalObj(Class)                                                  ((Class *)self.originalObj)
#define originalObjIsClass(Class)                                           [self.originalObj isKindOfClass:[Class class]]
#define AssertIsView                                                        NSAssert(originalObjIsClass(UIView), @"%@ 非view对象", self.originalObj);
#define AssertNotIsView                                                     NSAssert(!originalObjIsClass(UIView), @"%@ 是view对象", self.originalObj);
#define AssertIsLabel                                                       NSAssert(originalObjIsClass(UILabel), @"%@ 非label对象", self.originalObj);
#define AssertIsTextField                                                   NSAssert(originalObjIsClass(UITextField), @"%@ 非textField对象", self.originalObj);
#define AssertIsTextView                                                    NSAssert(originalObjIsClass(UITextView), @"%@ 非textView对象", self.originalObj);
#define AssertIsButton                                                      NSAssert(originalObjIsClass(UIButton), @"%@ 非button对象", self.originalObj);
#define AssertIsScrollView                                                  NSAssert(originalObjIsClass(UIScrollView), @"%@ 非scrollView对象", self.originalObj);
#define AssertIsTableView                                                   NSAssert(originalObjIsClass(UITableView), @"%@ 非tableView对象", self.originalObj);
#define AssertIsCollectionView                                              NSAssert(originalObjIsClass(UICollectionView), @"%@ 非collectionView对象", self.originalObj);
#define AssertIsAlertController                                             NSAssert(originalObjIsClass(UIAlertController), @"%@ 非alertController对象", self.originalObj);
#define AssertIsAlertAction                                                 NSAssert(originalObjIsClass(UIAlertAction), @"%@ 非alertAction对象", self.originalObj);
#define AssertIsAttributedString                                            NSAssert(originalObjIsClass(NSMutableAttributedString), @"%@ 非attributedString对象", self.originalObj);

#define AssertIsLabelOrTextFieldOrTextView                                  NSAssert(originalObj(UILabel) || originalObj(UITextField) || originalObj(UITextView), @"%@ 非LabelOrTextFieldOrTextView对象", self.originalObj);
#define AssertIsButtonOrTextField                                           NSAssert(originalObj(UIButton) || originalObj(UITextField), @"%@ 非button、textField对象", self.originalObj);
#define AssertIsTextFieldOrTextView                                         NSAssert(originalObj(UITextField) || originalObj(UITextView), @"%@ 非textField、textView对象", self.originalObj);
#define AssertIsTextFieldOrTextViewOrTableViewOrCollectionViewOrScrollView  NSAssert(originalObj(UITextField) || originalObj(UITextView) || originalObj(UITableView) || originalObj(UICollectionView) || originalObj(UIScrollView), @"%@ 非textField、textView、tableView、collectionView、scrollView对象", self.originalObj);
#define AssertIsTableViewOrCollectionView                                   NSAssert(originalObj(UITableView) || originalObj(UICollectionView), @"%@ 非tableView、collectionView对象", self.originalObj);



@interface MSChainMaker ()
{
    /** 有渐变 */
    BOOL _hasGradientLayer;
    /** 有圆角 */
    BOOL _hasCorner;
    /** 有边线 */
    BOOL _hasBorderLine;
    /** 有阴影 */
    BOOL _hasShadow;
    /** layer动画 */
    BOOL _lineAnimation;
    /** 有设置按钮文字图片位置 */
    BOOL _hasButtonType;
}

//圆角
/** 圆角半径 */
@property (nonatomic, assign)           CGFloat             cornerRadii;
/** 左上角圆角半径 */
@property (nonatomic, assign)           CGFloat             topLeftCornerRadii;
/** 左下角圆角半径 */
@property (nonatomic, assign)           CGFloat             bottomLeftCornerRadii;
/** 右下角圆角半径 */
@property (nonatomic, assign)           CGFloat             bottomRightCornerRadii;
/** 右上角圆角半径 */
@property (nonatomic, assign)           CGFloat             topRightCornerRadii;
//边线
/** 圆角类型 */
@property (nonatomic, assign)           MSBorderSideType    borderSideType;
/** 线宽(粗) */
@property (nonatomic, assign)           CGFloat             lineWidth;
/** 线颜色 */
@property (nonatomic, weak)             UIColor             *lineColor;
/** 虚线的偏移量(可动画属性，修改后会触发隐式动画) */
@property (nonatomic, assign)           CGFloat             lineDashPhase;
/** 虚线-线长&线间距，lineDashPattern为线性模版，这是一个NSNumber的数组，索引从1开始记，奇数位数值表示实线长度，偶数位数值表示空白长度 */
@property (nonatomic, strong)           NSArray<NSNumber *> *lineDashPattern;
//阴影
/** 阴影颜色 */
@property (nonatomic, strong)           UIColor             *shadowColor;
/** 阴影便宜量 */
@property (nonatomic, assign)           CGSize              shadowOffset;
/** 阴影透明度 */
@property (nonatomic, assign)           CGFloat             shadowOpacity;
/** 阴影半径 */
@property (nonatomic, assign)           CGFloat             shadowRadius;
/** 圆角半径，非阴影圆角大小用cornerRadii设置 */
@property (nonatomic, assign)           CGFloat             cornerRadius;
//渐变
/** 渐变色起点 */
@property (nonatomic, assign)           CGPoint             startPoint;
/** 渐变色终点 */
@property (nonatomic, assign)           CGPoint             endPoint;
/** 渐变色色值 */
@property (nonatomic, strong)           NSArray<UIColor *>  *colors;
/** 渐变色分割点 */
@property (nonatomic, strong, nullable) NSArray<NSNumber *> *locations;
/** 渐变色-贝塞尔曲线 */
@property (nonatomic, strong)           UIBezierPath        *shadowPath;
//layer动画
/** 指定属性动画
 常用的animationWithKeyPath值的总结：
 ransform.scale                      比例转换                                        @(0.8)
 transform.scale.x                  宽的比例                                        @(0.8)
 transform.scale.y                  高的比例                                        @(0.8)
 transform.rotation.x               围绕x轴旋转                                  @(M_PI)
 transform.rotation.y               围绕y轴旋转                                  @(M_PI)
 transform.rotation.z               围绕z轴旋转                                  @(M_PI)
 cornerRadius                        圆角的设置                                    @(50)
 backgroundColor                  背景颜色的变化                             (id)[UIColor purpleColor].CGColor
 bounds                                  大小，中心不变                             [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
 position                                 位置(中心点的改变)                       [NSValue valueWithCGPoint:CGPointMake(300, 300)];
 contents                                内容，比如UIImageView的图片    imageAnima.toValue = (id)[UIImage imageNamed:@"to"].CGImage;
 opacity                                  透明度                                           @(0.7)
 contentsRect.size.width        横向拉伸缩放                               @(0.4)最好是0~1之间的
 strokeEnd                              曲线绘制过程                               @0
 locations                               渐变色-分割点变化                        @[@0, @0, @0.25]
 */
@property (nonatomic, assign)           NSString            *lineAnimation_keyPath;
@property (nonatomic, assign)           CFTimeInterval      lineAnimation_duration;
@property (nonatomic, strong)           id                  lineAnimation_fromValue;
@property (nonatomic, strong)           id                  lineAnimation_toValue;
/** 重复次数，默认HUGE */
@property (nonatomic, assign)           CGFloat             lineAnimation_repeatCount;
//button
/** 按钮类型 */
@property (nonatomic, assign)           MSButtonModel       buttonModel;
/** 按钮icon与title间距 */
@property (nonatomic, assign)           CGFloat             buttonSpace;

@end

@implementation MSChainMaker

/** init */
- (instancetype)init
{
    self = [super init];
    if (self) {
        // 1、圆角
        _topLeftCornerRadii = 0.0;
        _bottomLeftCornerRadii = 0.0;
        _bottomRightCornerRadii = 0.0;
        _topRightCornerRadii = 0.0;
        // 2、边线
        _borderSideType = MSBorderSideTypeAll;
        _lineWidth = 0.5;
        _lineColor = UIColor.clearColor;
        _lineDashPhase = 0;
        _lineDashPattern = @[];
        // 3、阴影
        _shadowColor = UIColor.clearColor;
        _shadowOffset = CGSizeZero;
        _shadowOpacity = 0.6;
        _shadowRadius = 0.0;
        _cornerRadius = 0.0;
        // 4、渐变
        self.startPoint = CGPointZero;
        self.endPoint = CGPointMake(0, 1);
        // 5、动画
        _lineAnimation = NO;
        _lineAnimation_keyPath = @"strokeEnd";
        _lineAnimation_duration = 0;
        _lineAnimation_fromValue = @0.1;
        _lineAnimation_toValue = @0.9;
        _lineAnimation_repeatCount = HUGE;
    }
    return self;
}
/** 设置 view对象 */
- (void)setOriginalObj:(id)originalObj
{
    _originalObj = originalObj;
    
    @weakify(self);
    if ([originalObj respondsToSelector:@selector(layoutSubviews)])
    {
        // 监听 view 布局变化
        [[originalObj rac_signalForSelector:@selector(layoutSubviews)] subscribeNext:^(RACTuple * _Nullable x) {
            
            @strongify(self);
            [self frameDidChanged];
        }];
    }
}
/** frame 更新后同步更新圆角/边线/渐变色/按钮图片与文字位置*/
- (void)frameDidChanged
{
    if (!_hasCorner && _hasBorderLine)
    {
        //直角边线
        self.ms_drawBorderLine();
    }
    else if (_hasCorner || _hasBorderLine)
    {
        //圆角边线
        self.ms_drawCornerAndBorderLine();
    }
    
    if (_hasShadow)
    {
        //阴影
        self.ms_drawShadow();
    }
    
    if (_hasGradientLayer)
    {
        //渐变色
        self.ms_drawGradientLayer();
    }
    
    if (_hasButtonType)
    {
        //按钮文字与图片位置
        self.ms_resetButton();
    }
    
    if (_lineAnimation)
    {
        self.ms_addLayerAnimation(self.lineAnimation_keyPath, self.lineAnimation_duration, self.lineAnimation_fromValue, self.lineAnimation_toValue, self.lineAnimation_repeatCount);
    }
}


#pragma mark - view
/** frame */
- (MSChainMaker *(^)(CGFloat x, CGFloat y, CGFloat width, CGFloat height))ms_frame
{
    return ^(CGFloat x, CGFloat y, CGFloat width, CGFloat height) {
        
        AssertIsView
        originalObj(UIView).frame = CGRectMake(x, y, width, height);
        
        return self;
    };
}
/** center */
- (MSChainMaker *(^)(CGFloat x, CGFloat y))ms_center
{
    return ^(CGFloat x, CGFloat y) {
        
        AssertIsView
        originalObj(UIView).center = CGPointMake(x, y);
        return self;
    };
}
/** 背景颜色 */
- (MSChainMaker *(^)(UIColor *backgroundColor))ms_backgroundColor
{
    return ^(UIColor *backgroundColor) {
        
        AssertIsView
        originalObj(UIView).backgroundColor = backgroundColor;
        return self;
    };
}
/** 色调 */
- (MSChainMaker * _Nonnull (^)(UIColor *tintColor))ms_tintColor
{
    return ^(UIColor *tintColor) {
        
        AssertIsView
        originalObj(UIView).tintColor = tintColor;
        return self;
    };
}
/** tag */
- (MSChainMaker *(^)(NSInteger tag))ms_tag
{
    return ^(NSInteger tag) {
        
        AssertIsView
        originalObj(UIView).tag = tag;
        return self;
    };
}
/** 添加到父视图 */
- (MSChainMaker *(^)(UIView *superView))ms_addToSuperView
{
    return ^(UIView *superView) {
        
        AssertIsView
        [superView addSubview:originalObj(UIView)];
        return self;
    };
}
/** 添加约束 */
- (MSChainMaker *(^)(void (^mas_makeConstraints)(MASConstraintMaker *make)))ms_makeConstraints
{
    return ^(void (^mas_makeConstraints)(MASConstraintMaker *make)){
        
        AssertIsView
        [originalObj(UIView) mas_remakeConstraints:mas_makeConstraints];
        return self;
    };
}
/** hidden */
- (MSChainMaker *(^)(BOOL hidden))ms_hidden
{
    return ^(BOOL hidden) {
        
        AssertIsView
        originalObj(UIView).hidden = hidden;
        return self;
    };
}
- (MSChainMaker * _Nonnull (^)(BOOL userInteractionEnabled))ms_userInteractionEnabled
{
    return ^(BOOL userInteractionEnabled) {
        
        AssertIsView
        originalObj(UIView).userInteractionEnabled = userInteractionEnabled;
        return self;
    };
}
- (MSChainMaker * _Nonnull (^)(UIGestureRecognizer *ges, id target, SEL action))ms_addGestureRecognizer
{
    return ^(UIGestureRecognizer *ges, id target, SEL action) {
        
        AssertIsView
        [ges addTarget:target action:action];
        [originalObj(UIView) addGestureRecognizer:ges];
        return self.ms_userInteractionEnabled(YES);
    };
}
/** 角标文字 */
- (MSChainMaker * _Nonnull (^)(NSString * _Nonnull))ms_badgeText
{
    return ^(NSString *badgeText) {
        
        AssertIsView
        [originalObj(UIView) bringSubviewToFront:originalObj(UIView).ms_badgeView];
        originalObj(UIView).ms_badgeView.text = badgeText;
        [originalObj(UIView).ms_badgeView sizeToFit];
        CGFloat size = MAX(originalObj(UIView).ms_badgeView.ms_width+2, originalObj(UIView).ms_badgeView.ms_height+2);
        
        [originalObj(UIView).ms_badgeView ms_makeChains:^(MSChainMaker * _Nonnull make) {
            
            make.ms_cornerRadii(size / 2.0);
        }];
        
        [originalObj(UIView).ms_badgeView mas_updateConstraints:^(MASConstraintMaker *make) {
            
            make.width.height.mas_equalTo(size);
        }];
        
        return self;
    };
}
/** 角标距离superView的top */
- (MSChainMaker * _Nonnull (^)(CGFloat))ms_badgeEdge
{
    return ^(CGFloat ms_badgeEdge) {
        
        AssertIsView
        [originalObj(UIView) bringSubviewToFront:originalObj(UIView).ms_badgeView];
        [originalObj(UIView).ms_badgeView mas_updateConstraints:^(MASConstraintMaker *make) {
            
            make.top.mas_equalTo(ms_badgeEdge);
            make.right.mas_equalTo(-ms_badgeEdge);
        }];
        return self;
    };
}
/** 角标文字颜色 */
- (MSChainMaker * _Nonnull (^)(UIColor * _Nonnull))ms_badgeTextColor
{
    return ^(UIColor *badgeTextColor) {
        
        AssertIsView
        [originalObj(UIView) bringSubviewToFront:originalObj(UIView).ms_badgeView];
        originalObj(UIView).ms_badgeView.textColor = badgeTextColor;
        return self;
    };
}
/** 角标背景颜色 */
- (MSChainMaker * _Nonnull (^)(UIColor * _Nonnull))ms_badgeBackgroundColor
{
    return ^(UIColor *badgeBackgroundColor) {
        
        AssertIsView
        [originalObj(UIView) bringSubviewToFront:originalObj(UIView).ms_badgeView];
        originalObj(UIView).ms_badgeView.backgroundColor = badgeBackgroundColor;
        return self;
    };
}
/** 底图(view)  */
- (MSChainMaker *(^)(UIImage *image))ms_layerImage
{
    return ^(UIImage *image) {
        
        originalObj(UIView).layer.contents = (id)image.CGImage;
        
        return self;
    };
}


#pragma mark - 圆角、边线
/** 圆角半径(view) */
- (MSChainMaker *(^)(CGFloat cornerRadii))ms_cornerRadii
{
    return ^(CGFloat cornerRadii) {
        
        self.cornerRadii = cornerRadii;
        self.topLeftCornerRadii = cornerRadii;
        self.bottomLeftCornerRadii = cornerRadii;
        self.bottomRightCornerRadii = cornerRadii;
        self.topRightCornerRadii = cornerRadii;
        self->_hasCorner = YES;
        
        return self.ms_drawCornerAndBorderLine();
    };
}
/** 左上角半径(view)  */
- (MSChainMaker *(^)(CGFloat topLeftCornerRadii))ms_topLeftCornerRadii
{
    return ^(CGFloat topLeftCornerRadii) {
        
        self.topLeftCornerRadii = topLeftCornerRadii;
        self->_hasCorner = YES;
        
        return self.ms_drawCornerAndBorderLine();
    };
}
/** 左下角半径(view)  */
- (MSChainMaker *(^)(CGFloat bottomLeftCornerRadii))ms_bottomLeftCornerRadii
{
    return ^(CGFloat bottomLeftCornerRadii) {
        
        self.bottomLeftCornerRadii = bottomLeftCornerRadii;
        self->_hasCorner = YES;
        
        return self.ms_drawCornerAndBorderLine();
    };
}
/** 右下角半径(view)  */
- (MSChainMaker *(^)(CGFloat bottomRightCornerRadii))ms_bottomRightCornerRadii
{
    return ^(CGFloat bottomRightCornerRadii) {
        
        self.bottomRightCornerRadii = bottomRightCornerRadii;
        self->_hasCorner = YES;
        
        return self.ms_drawCornerAndBorderLine();
    };
}
/** 右上角半径(view)  */
- (MSChainMaker *(^)(CGFloat topRightCornerRadii))ms_topRightCornerRadii
{
    return ^(CGFloat topRightCornerRadii) {
        
        self.topRightCornerRadii = topRightCornerRadii;
        self->_hasCorner = YES;
        
        return self.ms_drawCornerAndBorderLine();
    };
}
/** 边线宽(view)  */
- (MSChainMaker *(^)(CGFloat lineWidth))ms_lineWidth
{
    return ^(CGFloat lineWidth) {
        
        self.lineWidth = lineWidth;
        self->_hasBorderLine = YES;
        
        return self.ms_drawCornerAndBorderLine();
    };
}
/** 边线颜色(view)  */
- (MSChainMaker *(^)(UIColor *lineColor))ms_lineColor
{
    return ^(UIColor *lineColor) {
        
        self.lineColor = lineColor;
        self->_hasBorderLine = YES;
        
        return self.ms_drawCornerAndBorderLine();
    };
}
/** 虚线-线型模版的起始位置，即，如果lineDashPattern设置为@[2,2,3,4],lineDashPhase即为第一个长度为2的线的起始位置 */
- (MSChainMaker * _Nonnull (^)(CGFloat))ms_lineDashPhase
{
    return ^(CGFloat lineDashPhase) {
        
        self.lineDashPhase = lineDashPhase;
        self->_hasBorderLine = YES;
        
        return self.ms_drawCornerAndBorderLine();
    };
}
/** 虚线-线长&线间距，lineDashPattern为线性模版，这是一个NSNumber的数组，索引从1开始记，奇数位数值表示实线长度，偶数位数值表示空白长度 */
- (MSChainMaker * _Nonnull (^)(NSArray<NSNumber *> * _Nonnull))ms_lineDashPattern
{
    return ^(NSArray<NSNumber *> *lineDashPattern) {
        
        self.lineDashPattern = lineDashPattern;
        self->_hasBorderLine = YES;
        
        return self.ms_drawCornerAndBorderLine();
    };
}
/** 绘制圆角和边线 */
- (MSChainMaker * _Nonnull (^)(void))ms_drawCornerAndBorderLine
{
    return ^ {
        
        AssertIsView
        CGRect frame = originalObj(UIView).bounds;
        CGFloat width = frame.size.width;
        CGFloat height = frame.size.height;
        
        if (width > 0 && height > 0)
        {
            NSArray *layers = originalObj(UIView).layer.sublayers;
            for (int i = 0; i < layers.count; i++)
            {
                CALayer *layer = layers[i];
                if ([layer isKindOfClass:[CAShapeLayer class]])
                {
                    // 移除旧的边线
                    [layer removeFromSuperlayer];
                }
            }
            
            UIBezierPath *bezierPath = [UIBezierPath bezierPath];
            bezierPath.lineWidth = 1.0;
            bezierPath.lineCapStyle = kCGLineCapRound;
            bezierPath.lineJoinStyle = kCGLineJoinRound;
            
            
            //起点
            [bezierPath moveToPoint:CGPointMake(self.topLeftCornerRadii, 0)];
            //上边直线
            [bezierPath addLineToPoint:CGPointMake(width - self.topRightCornerRadii, 0)];
            //右上角圆弧
            [bezierPath addArcWithCenter:CGPointMake(width - self.topRightCornerRadii, self.topRightCornerRadii)
                                  radius:self.topRightCornerRadii
                              startAngle:1.5 * M_PI
                                endAngle:2 * M_PI
                               clockwise:YES];
            //右边直线
            [bezierPath addLineToPoint:CGPointMake(width, height - self.bottomRightCornerRadii)];
            //右下角圆弧
            [bezierPath addArcWithCenter:CGPointMake(width - self.bottomRightCornerRadii, height - self.bottomRightCornerRadii)
                                  radius:self.bottomRightCornerRadii
                              startAngle:0
                                endAngle:0.5 * M_PI
                               clockwise:YES];
            // 下边直线
            [bezierPath addLineToPoint:CGPointMake(self.bottomLeftCornerRadii, height)];
            //左下角圆弧
            [bezierPath addArcWithCenter:CGPointMake(self.bottomLeftCornerRadii, height - self.bottomLeftCornerRadii)
                                  radius:self.bottomLeftCornerRadii
                              startAngle:0.5 * M_PI
                                endAngle:M_PI
                               clockwise:YES];
            // 左边直线
            [bezierPath addLineToPoint:CGPointMake(0, self.topLeftCornerRadii)];
            //左上角圆弧
            [bezierPath addArcWithCenter:CGPointMake(self.topLeftCornerRadii, self.topLeftCornerRadii)
                                  radius:self.topLeftCornerRadii
                              startAngle:M_PI
                                endAngle:1.5 * M_PI
                               clockwise:YES];
            
            CAShapeLayer *layer = [CAShapeLayer layer];
            layer.path = bezierPath.CGPath;
            layer.fillColor = UIColor.clearColor.CGColor;
            layer.lineWidth = self.lineWidth;
            layer.strokeColor = self.lineColor.CGColor;
            layer.lineDashPhase = self.lineDashPhase;
            layer.lineDashPattern = self.lineDashPattern;
            [originalObj(UIView).layer addSublayer:layer];
            
            CAShapeLayer *maskLayer = [CAShapeLayer layer];
            maskLayer.frame = CGRectMake(0, 0, width, height);
            maskLayer.path = bezierPath.CGPath;
            originalObj(UIView).layer.mask = maskLayer;
        }
        
        return self;
    };
}
/** 直角边线边类型，上下左右(view)  */
- (MSChainMaker *(^)(MSBorderSideType borderSideType))ms_borderSideType
{
    return ^(MSBorderSideType borderSideType) {
        
        self.borderSideType = borderSideType;
        self->_hasBorderLine = YES;
        
        return self.ms_drawBorderLine();
    };
}
/** 绘制直角边线*/
- (MSChainMaker * _Nonnull (^)(void))ms_drawBorderLine
{
    return ^ {
        
        AssertIsView
        CGFloat width = originalObj(UIView).bounds.size.width;
        CGFloat height = originalObj(UIView).bounds.size.height;
        
        if (width > 0 && height > 0)
        {
            NSArray *layers = originalObj(UIView).layer.sublayers;
            for (int i = 0; i < layers.count; i++)
            {
                CALayer *layer = layers[i];
                if ([layer isKindOfClass:[CAShapeLayer class]])
                {
                    // 移除旧的边线
                    [layer removeFromSuperlayer];
                }
            }
            
            if (self.borderSideType == MSBorderSideTypeAll)
            {
                self.borderSideType = MSBorderSideTypeTop | MSBorderSideTypeLeft | MSBorderSideTypeBottom | MSBorderSideTypeRight;
            }
            
            if (self.borderSideType & MSBorderSideTypeTop)
            {
                [originalObj(UIView).layer addSublayer:[self ms_addLineOriginPoint:CGPointZero
                                                                         toPoint:CGPointMake(width, 0)
                                                                           color:self.lineColor
                                                                     borderWidth:self.lineWidth]];
            }
            
            if (self.borderSideType & MSBorderSideTypeLeft)
            {
                [originalObj(UIView).layer addSublayer:[self ms_addLineOriginPoint:CGPointZero
                                                                         toPoint:CGPointMake(0,
                                                                                             height)
                                                                           color:self.lineColor
                                                                     borderWidth:self.lineWidth]];
            }
            
            if (self.borderSideType & MSBorderSideTypeBottom)
            {
                [originalObj(UIView).layer addSublayer:[self ms_addLineOriginPoint:CGPointMake(0, height)
                                                                         toPoint:CGPointMake(width, height)
                                                                           color:self.lineColor
                                                                     borderWidth:self.lineWidth]];
            }
            
            if (self.borderSideType & MSBorderSideTypeRight)
            {
                [originalObj(UIView).layer addSublayer:[self ms_addLineOriginPoint:CGPointMake(width, 0)
                                                                         toPoint:CGPointMake(width, height)
                                                                           color:self.lineColor
                                                                     borderWidth:self.lineWidth]];
            }
        }
        
        self->_hasBorderLine = YES;
        
        return self;
    };
}


#pragma mark - 阴影
/** 阴影颜色(view)  */
- (MSChainMaker *(^)(UIColor *shadowColor))ms_shadowColor
{
    return ^(UIColor *shadowColor) {
        
        self.shadowColor = shadowColor;
        self->_hasShadow = YES;
        
        return self.ms_drawShadow();
    };
}
/** 阴影偏移(view)  */
- (MSChainMaker *(^)(CGSize shadowOffset))ms_shadowOffset
{
    return ^(CGSize shadowOffset) {
        
        self.shadowOffset = shadowOffset;
        self->_hasShadow = YES;
        
        return self.ms_drawShadow();
    };
}
/** 阴影不透明度(view)  */
- (MSChainMaker *(^)(CGFloat shadowOpacity))ms_shadowOpacity
{
    return ^(CGFloat shadowOpacity) {
        
        self.shadowOpacity = shadowOpacity;
        self->_hasShadow = YES;
        
        return self.ms_drawShadow();
    };
}
/** 阴影半径(view)  */
- (MSChainMaker *(^)(CGFloat shadowRadius))ms_shadowRadius
{
    return ^(CGFloat shadowRadius) {
        
        self.shadowRadius = shadowRadius;
        self->_hasShadow = YES;
        
        return self.ms_drawShadow();
    };
}
/** 阴影角半径(view)  */
- (MSChainMaker * _Nonnull (^)(CGFloat))ms_shadowCornerRadius
{
    return ^(CGFloat shadowCornerRadius) {
        
        self.cornerRadius = shadowCornerRadius;
        self->_hasShadow = YES;
        
        return self.ms_drawShadow();
    };
}
/** 绘制阴影（依赖控件frame ！！！） */
- (MSChainMaker * _Nonnull (^)(void))ms_drawShadow
{
    return ^ {
        
        AssertIsView
        CGFloat width = originalObj(UIView).bounds.size.width;
        CGFloat height = originalObj(UIView).bounds.size.height;
        
        if (width > 0 && height > 0)
        {
            originalObj(UIView).layer.shadowColor = self.shadowColor.CGColor;
            originalObj(UIView).layer.shadowOffset = self.shadowOffset;
            originalObj(UIView).layer.shadowOpacity = self.shadowOpacity;
            originalObj(UIView).layer.shadowRadius = self.shadowRadius;
            originalObj(UIView).layer.cornerRadius = self.cornerRadius;
            UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, width, height)];
            originalObj(UIView).layer.shadowPath = bezierPath.CGPath;
        }
        
        return self;
    };
}


#pragma mark - 渐变色
/** 渐变色-起始点 */
- (MSChainMaker *(^)(CGPoint startPoint))ms_startPoint
{
    return ^(CGPoint startPoint) {
        
        self.startPoint = startPoint;
        self->_hasGradientLayer = YES;
        
        return self.ms_drawGradientLayer();
    };
}
/** 渐变色-结束点 */
- (MSChainMaker *(^)(CGPoint endPoint))ms_endPoint
{
    return ^(CGPoint endPoint) {
        
        self.endPoint = endPoint;
        self->_hasGradientLayer = YES;
        
        return self.ms_drawGradientLayer();
    };
}
/** 渐变色-颜色数组 */
- (MSChainMaker * _Nonnull (^)(NSArray<UIColor *> * _Nullable))ms_colors
{
    return ^(NSArray<UIColor *> * _Nullable colors) {
        
        self.colors = colors;
        self->_hasGradientLayer = YES;
        
        return self.ms_drawGradientLayer();
    };
}
/** 渐变色-分割点 */
- (MSChainMaker *(^)(NSArray<NSNumber *> *locations))ms_locations
{
    return ^(NSArray<NSNumber *> *locations) {
        
        self.locations = locations;
        self->_hasGradientLayer = YES;
        
        return self.ms_drawGradientLayer();
    };
}
/** 渐变色-贝塞尔曲线 */
- (MSChainMaker * _Nonnull (^)(id))ms_shadowPath
{
    return ^(id shadowPath) {
        
        self.shadowPath = shadowPath;
        self->_hasGradientLayer = YES;
        
        return self.ms_drawGradientLayer();
    };
}
/** 渐变色-layer */
- (MSChainMaker * _Nonnull (^)(void))ms_drawGradientLayer
{
    return ^ {
        
        AssertIsView
        CGFloat width = originalObj(UIView).bounds.size.width;
        CGFloat height = originalObj(UIView).bounds.size.height;
        
        if (width > 0 && height > 0)
        {
            NSMutableArray *array = [NSMutableArray array];
            for (UIColor *color in self.colors)
            {
                [array addObject:(id)color.CGColor];
            }
            
            CAGradientLayer *gradientLayer = ms_newGradientLayer();
            gradientLayer.frame = originalObj(UIView).bounds;
            gradientLayer.startPoint = self.startPoint;
            gradientLayer.endPoint = self.endPoint;
            gradientLayer.colors = array;
            gradientLayer.shadowPath = self.shadowPath.CGPath;
            
            NSArray *layers = originalObj(UIView).layer.sublayers;
            for (int i = 0; i < layers.count; i++)
            {
                CALayer *layer = layers[i];
                if ([layer isKindOfClass:[CAGradientLayer class]])
                {
                    // 移除旧的渐渐变色
                    [layer removeFromSuperlayer];
                }
            }
            
            [originalObj(UIView).layer insertSublayer:gradientLayer atIndex:0];
        }
        
        return self;
    };
}


#pragma mark - layer animation
/** 添加CABasicAnimation动画 */
- (MSChainMaker *(^)(NSString *lineAnimation_keyPath, CFTimeInterval duration, id fromValue, id toValue, CGFloat repeatCount))ms_addLayerAnimation
{
    return ^(NSString *lineAnimation_keyPath, CFTimeInterval duration, id fromValue, id toValue, CGFloat repeatCount) {
        
        self.lineAnimation_keyPath = lineAnimation_keyPath;
        self.lineAnimation_duration = duration;
        self.lineAnimation_fromValue = fromValue;
        self.lineAnimation_toValue = toValue;
        self.lineAnimation_repeatCount = repeatCount;
        self->_lineAnimation = YES;
        
        CALayer *layer = originalObj(UIView).layer;
        for (CALayer *subLayer in originalObj(UIView).layer.sublayers)
        {
            if ([subLayer isKindOfClass:CAShapeLayer.class] ||
                [subLayer isKindOfClass:CAGradientLayer.class])
            {
                layer = subLayer;
            }
        }
        
        CABasicAnimation *bas = [CABasicAnimation animationWithKeyPath:self.lineAnimation_keyPath];
        bas.duration = self.lineAnimation_duration;
        bas.fromValue = self.lineAnimation_fromValue;
        bas.toValue = self.lineAnimation_toValue;
        bas.repeatCount = self.lineAnimation_repeatCount;
        //添加动画
        [layer addAnimation:bas forKey:@"key"];
        
        return self;
    };
}
/** 移除CABasicAnimation动画 */
- (MSChainMaker *(^)(NSString *lineAnimation_keyPath))ms_removeLayerAnimation
{
    return ^(NSString *lineAnimation_keyPath) {
        
        CALayer *layer = originalObj(UIView).layer.sublayers.lastObject;
        //移除动画
        [layer removeAnimationForKey:@"key"];
        
        return self;
    };
}


#pragma mark - label、textField、textView 公有
/** 文字 */
- (MSChainMaker *(^)(NSString *text))ms_text
{
    return ^(NSString *text) {
        
        AssertIsLabelOrTextFieldOrTextView
        if (originalObjIsClass(UILabel))
        {
            originalObj(UILabel).text = text;
        }
        else if (originalObjIsClass(UITextField))
        {
            originalObj(UITextField).text = text;
        }
        else if (originalObjIsClass(UITextView))
        {
            originalObj(UITextView).text = text;
        }
        
        return self;
    };
}
/** 富文本 */
- (MSChainMaker *(^)(NSAttributedString *attributedText))ms_attributedText
{
    return ^(NSAttributedString *attributedText) {
        
        AssertIsLabelOrTextFieldOrTextView
        if (originalObjIsClass(UILabel))
        {
            originalObj(UILabel).attributedText = attributedText;
        }
        else if (originalObjIsClass(UITextField))
        {
            originalObj(UITextField).attributedText = attributedText;
        }
        else if (originalObjIsClass(UITextView))
        {
            originalObj(UITextView).attributedText = attributedText;
        }
        
        return self;
    };
}
/** 字体 */
- (MSChainMaker *(^)(UIFont *font))ms_font
{
    return ^(UIFont *font) {
        
        AssertIsLabelOrTextFieldOrTextView
        if (originalObjIsClass(UILabel))
        {
            originalObj(UILabel).font = font;
        }
        else if (originalObjIsClass(UITextField))
        {
            originalObj(UITextField).font = font;
        }
        else if (originalObjIsClass(UITextView))
        {
            originalObj(UITextView).font = font;
        }
        
        return self;
    };
}
/** 文字颜色 */
- (MSChainMaker *(^)(UIColor *textColor))ms_textColor
{
    return ^(UIColor *textColor) {
        
        AssertIsLabelOrTextFieldOrTextView
        if (originalObjIsClass(UILabel))
        {
            originalObj(UILabel).textColor = textColor;
        }
        else if (originalObjIsClass(UITextField))
        {
            originalObj(UITextField).textColor = textColor;
        }
        else if (originalObjIsClass(UITextView))
        {
            originalObj(UITextView).textColor = textColor;
        }
        
        return self;
    };
}
/** 文字对齐方式 */
- (MSChainMaker *(^)(NSTextAlignment textAlignment))ms_textAlignment
{
    return ^(NSTextAlignment textAlignment) {
        
        AssertIsLabelOrTextFieldOrTextView
        if (originalObjIsClass(UILabel))
        {
            originalObj(UILabel).textAlignment = textAlignment;
        }
        else if (originalObjIsClass(UITextField))
        {
            originalObj(UITextField).textAlignment = textAlignment;
        }
        else if (originalObjIsClass(UITextView))
        {
            originalObj(UITextView).textAlignment = textAlignment;
        }
        
        return self;
    };
}


#pragma mark - button、textfield 公有
/** 添加点击事件 */
- (MSChainMaker *(^)(id target, SEL action))ms_addTarget
{
    return ^(id target, SEL action) {
        
        AssertIsButtonOrTextField
        if (originalObjIsClass(UIButton))
        {
            [originalObj(UIButton) addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
        }
        else if (originalObjIsClass(UITextField))
        {
            [originalObj(UITextField) addTarget:target action:action forControlEvents:UIControlEventEditingChanged];
        }
        
        return self;
    };
}


#pragma mark - textField、textView 公有
/** 键盘类型 */
- (MSChainMaker *(^)(UIKeyboardType keyboardType))ms_keyboardType
{
    return ^(UIKeyboardType keyboardType) {
        
        AssertIsTextFieldOrTextView
        if (originalObjIsClass(UITextField))
        {
            originalObj(UITextField).keyboardType = keyboardType;
        }
        else if (originalObjIsClass(UITextView))
        {
            originalObj(UITextView).keyboardType = keyboardType;
        }
        
        return self;
    };
}
/** 成为第一响应者 */
- (MSChainMaker * _Nonnull (^)(void))ms_becomeFirstResponder
{
    return ^ {
        
        AssertIsTextFieldOrTextView
        if (originalObjIsClass(UITextField))
        {
            [originalObj(UITextField) becomeFirstResponder];
        }
        else if (originalObjIsClass(UITextView))
        {
            [originalObj(UITextView) becomeFirstResponder];
        }
        
        return self;
    };
}
/** 自定义键盘 */
- (MSChainMaker *(^)(UIView *inputView))ms_inputView
{
    return ^(UIView *inputView) {
        
        AssertIsTextFieldOrTextView
        if (originalObjIsClass(UITextField))
        {
            originalObj(UITextField).inputView = inputView;
        }
        else if (originalObjIsClass(UITextView))
        {
            originalObj(UITextView).inputView = inputView;
        }
        
        return self;
    };
}
/** 键盘上面自定义附件视图 */
- (MSChainMaker *(^)(UIView *inputAccessoryView))ms_inputAccessoryView
{
    return ^(UIView *inputAccessoryView) {
        
        AssertIsTextFieldOrTextView
        if (originalObjIsClass(UITextField))
        {
            originalObj(UITextField).inputAccessoryView = inputAccessoryView;
        }
        else if (originalObjIsClass(UITextView))
        {
            originalObj(UITextView).inputAccessoryView = inputAccessoryView;
        }
        
        return self;
    };
}


#pragma mark - textField、textView、tableView、collectionView、scrollView 公有
/** 设置delegate */
- (MSChainMaker *(^)(id delegate))ms_delegate
{
    return ^(id delegate) {
        
        AssertIsTextFieldOrTextViewOrTableViewOrCollectionViewOrScrollView
        if (originalObjIsClass(UITextField))
        {
            originalObj(UITextField).delegate = delegate;
        }
        else if (originalObjIsClass(UITextView))
        {
            originalObj(UITextView).delegate = delegate;
        }
        else if (originalObjIsClass(UITableView))
        {
            originalObj(UITableView).delegate = delegate;
        }
        else if (originalObjIsClass(UICollectionView))
        {
            originalObj(UICollectionView).delegate = delegate;
        }
        else if (originalObjIsClass(UIScrollView))
        {
            originalObj(UIScrollView).delegate = delegate;
        }
        
        return self;
    };
}


#pragma mark - tableView、collectionView 公有
/** 设置dataSource */
- (MSChainMaker *(^)(id dataSource))ms_dataSource
{
    return ^(id dataSource) {
        
        AssertIsTableViewOrCollectionView
        if (originalObjIsClass(UITableView))
        {
            originalObj(UITableView).dataSource = dataSource;
        }
        else if (originalObjIsClass(UICollectionView))
        {
            originalObj(UICollectionView).dataSource = dataSource;
        }
        
        return self;
    };
}
/** 注册cell（tableView、collectionView） */
- (MSChainMaker * _Nonnull (^)(id _Nonnull, NSString * _Nonnull))ms_registerCell
{
    return ^(id cellClass, NSString *identifier) {
        
        AssertIsTableViewOrCollectionView
        if (originalObjIsClass(UITableView))
        {
            [originalObj(UITableView) registerClass:cellClass forCellReuseIdentifier:identifier];
        }
        else if (originalObjIsClass(UICollectionView))
        {
            [originalObj(UICollectionView) registerClass:cellClass forCellWithReuseIdentifier:identifier];
        }
        
        return self;
    };
}


#pragma mark -
#pragma mark - label
/** 行数 */
- (MSChainMaker *(^)(NSInteger numberOfLines))ms_numberOfLines
{
    return ^(NSInteger numberOfLines) {
        
        AssertIsLabel
        originalObj(UILabel).numberOfLines = numberOfLines;
        
        return self;
    };
}
/** 断句模式 */
- (MSChainMaker *(^)(NSLineBreakMode lineBreakMode))ms_lineBreakMode
{
    return ^(NSLineBreakMode lineBreakMode) {
        
        AssertIsLabel
        originalObj(UILabel).lineBreakMode = lineBreakMode;
        
        return self;
    };
}
/** HTML字符串 */
- (MSChainMaker * _Nonnull (^)(NSString * _Nonnull))ms_htmlText
{
    return ^(NSString *htmlString) {
        
        AssertIsLabel
        NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUnicodeStringEncoding]
                                                                                              options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}
                                                                                   documentAttributes:nil
                                                                                                error:nil];
        NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
        paragraphStyle.lineSpacing = 3;
        [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, attributedString.mutableString.length)];
        
        originalObj(UILabel).attributedText = attributedString;
        
        return self;
    };
}


#pragma mark - button
/** 标题 */
- (MSChainMaker *(^)(NSString *title, UIControlState state))ms_title
{
    return ^(NSString *title, UIControlState state) {
        
        AssertIsButton
        [originalObj(UIButton) setTitle:title forState:state];
        
        return self;
    };
}
/** 标题 */
- (MSChainMaker *(^)(NSAttributedString *title, UIControlState state))ms_attributedTitle
{
    return ^(NSAttributedString *title, UIControlState state) {
        
        AssertIsButton
        [originalObj(UIButton) setAttributedTitle:title forState:state];
        
        return self;
    };
}
/** 标题字体 */
- (MSChainMaker *(^)(UIFont *font))ms_titleFont
{
    return ^(UIFont *font) {
        
        AssertIsButton
        originalObj(UIButton).titleLabel.font = font;
        
        return self;
    };
}
/** 标题颜色 */
- (MSChainMaker *(^)(UIColor *color, UIControlState state))ms_titleColor
{
    return ^(UIColor *color, UIControlState state) {
        
        AssertIsButton
        [originalObj(UIButton) setTitleColor:color forState:state];
        
        return self;
    };
}
/** 图片 */
- (MSChainMaker *(^)(UIImage *image, UIControlState state))ms_image
{
    return ^(UIImage *image, UIControlState state) {
        
        AssertIsButton
        [originalObj(UIButton) setImage:image forState:state];
        
        return self;
    };
}
/** 背景图片 */
- (MSChainMaker *(^)(UIImage *image, UIControlState state))ms_backgroundImage
{
    return ^(UIImage *image, UIControlState state) {
        
        AssertIsButton
        [originalObj(UIButton) setBackgroundImage:image forState:state];
        
        return self;
    };
}
/** 背景图片 */
- (MSChainMaker *(^)(NSString *url, UIImage *placeholderImage, UIControlState state))ms_backgroundImageURLString
{
    return ^(NSString *url, UIImage *placeholderImage, UIControlState state) {
        
        AssertIsButton
        [originalObj(UIButton) sd_setImageWithURL:MSURL(url)
                                         forState:state
                                 placeholderImage:placeholderImage];
        
        return self;
    };
}
/** 按钮图片文字排列类型 */
- (MSChainMaker * _Nonnull (^)(MSButtonModel model))ms_buttonType
{
    return ^(MSButtonModel model) {
        
        self.buttonModel = model;
        self->_hasButtonType = YES;
        return self.ms_resetButton();
    };
}
/** 图片与文字间距 */
- (MSChainMaker * _Nonnull (^)(CGFloat space))ms_space
{
    return ^(CGFloat space) {
        
        self.buttonSpace = space;
        self->_hasButtonType = YES;
        return self.ms_resetButton();
    };
}
/** 按钮文字与图片位置 */
- (MSChainMaker * _Nonnull (^)(void))ms_resetButton
{
    return ^ {
        
        AssertIsButton
        if (originalObj(UIButton).imageView.image && originalObj(UIButton).titleLabel.text.length > 0)
        {
            CGSize imageSize = originalObj(UIButton).imageView.image.size;
            CGSize titleSize = originalObj(UIButton).titleLabel.frame.size;
            if ([UIDevice currentDevice].systemVersion.floatValue >= 8.0)
            {
                titleSize = originalObj(UIButton).titleLabel.intrinsicContentSize;
            }
            
            switch (self.buttonModel)
            {
                case MSButtonModelDefault:
                {
                    [originalObj(UIButton) setImageEdgeInsets:UIEdgeInsetsMake(0,
                                                                               -self.buttonSpace / 2.0,
                                                                               0,
                                                                               self.buttonSpace / 2.0)];
                    
                    [originalObj(UIButton) setTitleEdgeInsets:UIEdgeInsetsMake(0,
                                                                               self.buttonSpace / 2.0,
                                                                               0,
                                                                               -self.buttonSpace / 2.0)];
                    originalObj(UIButton).contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
                }
                    break;
                case MSButtonModelTextAndImgHorizontal:
                {
                    [originalObj(UIButton) setImageEdgeInsets:UIEdgeInsetsMake(0,
                                                                               titleSize.width + self.buttonSpace / 2.0,
                                                                               0,
                                                                               -(titleSize.width + self.buttonSpace / 2.0))];
                    
                    [originalObj(UIButton) setTitleEdgeInsets:UIEdgeInsetsMake(0,
                                                                               -(imageSize.width + self.buttonSpace / 2.0),
                                                                               0,
                                                                               imageSize.width + self.buttonSpace / 2.0)];
                    originalObj(UIButton).contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
                }
                    break;
                case MSButtonModelImgAndTextVertical:
                {
                    [originalObj(UIButton) setImageEdgeInsets:UIEdgeInsetsMake(-(titleSize.height / 2 + self.buttonSpace / 2.0),
                                                                               0,
                                                                               titleSize.height / 2,
                                                                               -titleSize.width)];
                    
                    [originalObj(UIButton) setTitleEdgeInsets:UIEdgeInsetsMake(imageSize.height / 2,
                                                                               -imageSize.width,
                                                                               -(imageSize.height / 2 + self.buttonSpace / 2.0),
                                                                               0)];
                    originalObj(UIButton).contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
                }
                    break;
                case MSButtonModelTextAndImgVertical:
                {
                    [originalObj(UIButton) setImageEdgeInsets:UIEdgeInsetsMake(titleSize.height / 2 + self.buttonSpace / 2.0,
                                                                               0,
                                                                               -titleSize.height / 2,
                                                                               -titleSize.width)];
                    
                    [originalObj(UIButton) setTitleEdgeInsets:UIEdgeInsetsMake(-imageSize.height / 2,
                                                                               -imageSize.width,
                                                                               imageSize.height / 2 + self.buttonSpace / 2.0,
                                                                               0)];
                    originalObj(UIButton).contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
                }
                    break;
                default:
                    break;
            }
        }
        
        return self;
    };
}


#pragma mark - scrollView
/** 关闭自动调整滚动指示器集 */
- (MSChainMaker * _Nonnull (^)(void))ms_automaticallyAdjustsScrollIndicatorInsets
{
    return ^ {
        
        AssertIsScrollView
        if (@available(iOS 11.0, *))
        {
            originalObj(UIScrollView).contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
        }
        else if (@available(iOS 13.0, *))
        {
            originalObj(UIScrollView).automaticallyAdjustsScrollIndicatorInsets = NO;
        }
        return self;
    };
}
/** 方向锁 */
- (MSChainMaker * _Nonnull (^)(BOOL))ms_directionalLockEnabled
{
    return ^(BOOL directionalLockEnabled) {
        
        AssertIsScrollView
        originalObj(UIScrollView).directionalLockEnabled = directionalLockEnabled;
        return self;
    };
}
/** bounces */
- (MSChainMaker *(^)(BOOL bounces))ms_bounces
{
    return ^(BOOL bounces) {
        
        AssertIsScrollView
        originalObj(UIScrollView).bounces = bounces;
        return self;
    };
}
/** 如果“YES”且“bounces”为“YES”，则即使内容小于边界，也允许垂直拖动 */
- (MSChainMaker * _Nonnull (^)(BOOL))ms_alwaysBounceVertical
{
    return ^(BOOL alwaysBounceVertical) {
        
        AssertIsScrollView
        originalObj(UIScrollView).alwaysBounceVertical = alwaysBounceVertical;
        return self;
    };
}
/** 如果“YES”且“bounces”为“YES”，则即使内容小于边界，也允许水平拖动 */
- (MSChainMaker * _Nonnull (^)(BOOL))ms_alwaysBounceHorizontal
{
    return ^(BOOL alwaysBounceHorizontal) {
        
        AssertIsScrollView
        originalObj(UIScrollView).alwaysBounceVertical = alwaysBounceHorizontal;
        return self;
    };
}
/** pagingEnabled */
- (MSChainMaker *(^)(BOOL pagingEnabled))ms_pagingEnabled
{
    return ^(BOOL pagingEnabled) {
        
        AssertIsScrollView
        originalObj(UIScrollView).pagingEnabled = pagingEnabled;
        return self;
    };
}
/** scrollEnabled */
- (MSChainMaker *(^)(BOOL scrollEnabled))ms_scrollEnabled
{
    return ^(BOOL scrollEnabled) {
        
        AssertIsScrollView
        originalObj(UIScrollView).scrollEnabled = scrollEnabled;
        return self;
    };
}
/** showsVerticalScrollIndicator */
- (MSChainMaker *(^)(BOOL showsVerticalScrollIndicator))ms_showsVerticalScrollIndicator
{
    return ^(BOOL showsVerticalScrollIndicator) {
        
        AssertIsScrollView
        originalObj(UIScrollView).showsVerticalScrollIndicator = showsVerticalScrollIndicator;
        return self;
    };
}
/** showsVerticalScrollIndicator */
- (MSChainMaker *(^)(BOOL showsHorizontalScrollIndicator))ms_showsHorizontalScrollIndicator
{
    return ^(BOOL showsHorizontalScrollIndicator) {
        
        AssertIsScrollView
        originalObj(UIScrollView).showsHorizontalScrollIndicator = showsHorizontalScrollIndicator;
        return self;
    };
}
/** contentOffset */
- (MSChainMaker *(^)(CGPoint point))ms_contentOffset
{
    return ^(CGPoint point) {
        
        AssertIsScrollView
        originalObj(UIScrollView).contentOffset = point;
        return self;
    };
}
/** contentSize */
- (MSChainMaker *(^)(CGSize size))ms_contentSize
{
    return ^(CGSize size) {
        
        AssertIsScrollView
        originalObj(UIScrollView).contentSize = size;
        return self;
    };
}
/** contentInset */
- (MSChainMaker *(^)(UIEdgeInsets edgeInsets))ms_contentInset
{
    return ^(UIEdgeInsets edgeInsets) {
        
        AssertIsScrollView
        originalObj(UIScrollView).contentInset = edgeInsets;
        return self;
    };
}


#pragma mark - textField
/** 占位符 */
- (MSChainMaker *(^)(NSString *placeholder))ms_placeholder
{
    return ^(NSString *placeholder) {
        
        AssertIsTextField
        originalObj(UITextField).placeholder = placeholder;
        
        return self;
    };
}
/** 富文本占位符 */
- (MSChainMaker *(^)(NSAttributedString *attributedPlaceholder))ms_attributedPlaceholder
{
    return ^(NSAttributedString *attributedPlaceholder) {
        
        AssertIsTextField
        originalObj(UITextField).attributedPlaceholder = attributedPlaceholder;
        
        return self;
    };
}
/** 开始编辑时是否清除 */
- (MSChainMaker *(^)(BOOL clearsOnBeginEditing))ms_clearsOnBeginEditing
{
    return ^(BOOL clearsOnBeginEditing) {
        
        AssertIsTextField
        originalObj(UITextField).clearsOnBeginEditing = clearsOnBeginEditing;
        
        return self;
    };
}
/** 删除按钮模式 */
- (MSChainMaker *(^)(UITextFieldViewMode clearButtonMode))ms_clearButtonMode
{
    return ^(UITextFieldViewMode clearButtonMode) {
        
        AssertIsTextField
        originalObj(UITextField).clearButtonMode = clearButtonMode;
        
        return self;
    };
}
/** 左侧视图 */
- (MSChainMaker *(^)(UIView *leftView))ms_leftView
{
    return ^(UIView *leftView) {
        
        AssertIsTextField
        originalObj(UITextField).leftView = leftView;
        
        return self;
    };
}
/** 左侧视图模式 */
- (MSChainMaker *(^)(UITextFieldViewMode leftViewMode))ms_leftViewMode
{
    return ^(UITextFieldViewMode leftViewMode) {
        
        AssertIsTextField
        originalObj(UITextField).leftViewMode = leftViewMode;
        
        return self;
    };
}
/** 右侧视图 */
- (MSChainMaker *(^)(UIView *rightView))ms_rightView
{
    return ^(UIView *rightView) {
        
        AssertIsTextField
        originalObj(UITextField).rightView = rightView;
        
        return self;
    };
}
/** 右侧视图模式 */
- (MSChainMaker *(^)(UITextFieldViewMode rightViewMode))ms_rightViewMode
{
    return ^(UITextFieldViewMode rightViewMode) {
        
        AssertIsTextField
        originalObj(UITextField).rightViewMode = rightViewMode;
        
        return self;
    };
}


#pragma mark - tableView
/** 行高 */
- (MSChainMaker *(^)(CGFloat rowHeight))ms_rowHeight
{
    return ^(CGFloat rowHeight) {
        
        AssertIsTableView
        originalObj(UITableView).rowHeight = rowHeight;
        
        return self;
    };
}
/** 分组头部高 */
- (MSChainMaker *(^)(CGFloat sectionHeaderHeight))ms_sectionHeaderHeight
{
    return ^(CGFloat sectionHeaderHeight) {
        
        AssertIsTableView
        originalObj(UITableView).sectionHeaderHeight = sectionHeaderHeight;
        
        return self;
    };
}
/** 分组尾部高 */
- (MSChainMaker *(^)(CGFloat sectionFooterHeight))ms_sectionFooterHeight
{
    return ^(CGFloat sectionFooterHeight) {
        
        AssertIsTableView
        originalObj(UITableView).sectionFooterHeight = sectionFooterHeight;
        
        return self;
    };
}
/** 预估行高 */
- (MSChainMaker *(^)(CGFloat estimatedRowHeight))ms_estimatedRowHeight
{
    return ^(CGFloat estimatedRowHeight) {
        
        AssertIsTableView
        originalObj(UITableView).estimatedRowHeight = estimatedRowHeight;
        
        return self;
    };
}
/** 预估分组头部高 */
- (MSChainMaker *(^)(CGFloat estimatedSectionHeaderHeight))ms_estimatedSectionHeaderHeight
{
    return ^(CGFloat estimatedSectionHeaderHeight) {
        
        AssertIsTableView
        originalObj(UITableView).estimatedSectionHeaderHeight = estimatedSectionHeaderHeight;
        
        return self;
    };
}
/** 预估分组尾部高 */
- (MSChainMaker *(^)(CGFloat estimatedSectionFooterHeight))ms_estimatedSectionFooterHeight
{
    return ^(CGFloat estimatedSectionFooterHeight) {
        
        AssertIsTableView
        originalObj(UITableView).estimatedSectionFooterHeight = estimatedSectionFooterHeight;
        
        return self;
    };
}
/** default is YES. Controls whether rows can be selected when not in editing mode */
- (MSChainMaker * _Nonnull (^)(BOOL))ms_allowsSelection
{
    return ^(BOOL allowsSelection) {
        
        AssertIsTableView
        originalObj(UITableView).allowsSelection = allowsSelection;
        
        return self;
    };
}
/** default is NO. Controls whether multiple rows can be selected simultaneously */
- (MSChainMaker * _Nonnull (^)(BOOL))ms_allowsMultipleSelection
{
    return ^(BOOL allowsMultipleSelection) {
        
        AssertIsTableView
        originalObj(UITableView).allowsMultipleSelection = allowsMultipleSelection;
        
        return self;
    };
}
/** default is NO. Controls whether multiple rows can be selected simultaneously in editing mode */
- (MSChainMaker * _Nonnull (^)(BOOL))ms_allowsMultipleSelectionDuringEditing
{
    return ^(BOOL allowsMultipleSelectionDuringEditing) {
        
        AssertIsTableView
        originalObj(UITableView).allowsMultipleSelectionDuringEditing = allowsMultipleSelectionDuringEditing;
        
        return self;
    };
}
/** default is NO. Controls whether rows can be selected when in editing mode */
- (MSChainMaker * _Nonnull (^)(BOOL))ms_allowsSelectionDuringEditing
{
    return ^(BOOL allowsSelectionDuringEditing) {
        
        AssertIsTableView
        originalObj(UITableView).allowsSelection = allowsSelectionDuringEditing;
        
        return self;
    };
}
/** 分割线类型 */
- (MSChainMaker * _Nonnull (^)(UITableViewCellSeparatorStyle separatorStyle))ms_separatorStyle
{
    return ^(UITableViewCellSeparatorStyle separatorStyle) {
        
        AssertIsTableView
        originalObj(UITableView).separatorStyle = separatorStyle;
        
        return self;
    };
}
/** 分割线颜色 */
- (MSChainMaker * _Nonnull (^)(UIColor *separatorColor))ms_separatorColor
{
    return ^(UIColor *separatorColor) {
        
        AssertIsTableView
        originalObj(UITableView).separatorColor = separatorColor;
        
        return self;
    };
}
/** separatorInset */
- (MSChainMaker *(^)(UIEdgeInsets separatorInset))ms_separatorInset
{
    return ^(UIEdgeInsets separatorInset) {
        
        AssertIsTableView
        originalObj(UITableView).separatorInset = separatorInset;
        
        return self;
    };
}
/** tableHeaderView */
- (MSChainMaker *(^)(UIView *tableHeaderView))ms_tableHeaderView
{
    return ^(UIView *tableHeaderView) {
        
        AssertIsTableView
        originalObj(UITableView).tableHeaderView = tableHeaderView;
        
        return self;
    };
}
/** tableFooterView */
- (MSChainMaker *(^)(UIView *tableFooterView))ms_tableFooterView
{
    return ^(UIView *tableFooterView) {
        
        AssertIsTableView
        originalObj(UITableView).tableFooterView = tableFooterView;
        
        return self;
    };
}
/** 注册分组头部尾部视图 */
- (MSChainMaker *(^)(id aClass, NSString *identifier))ms_registerHeaderFooterView
{
    return ^(id aClass, NSString *identifier) {
        
        AssertIsTableView
        [originalObj(UITableView) registerClass:aClass forHeaderFooterViewReuseIdentifier:identifier];
        
        return self;
    };
}


#pragma mark - collectionView
/** layout（collectionView） */
- (MSChainMaker *(^)(UICollectionViewLayout *collectionViewLayout))ms_collectionViewLayout
{
    return ^(UICollectionViewLayout *collectionViewLayout) {
        
        AssertIsCollectionView
        originalObj(UICollectionView).collectionViewLayout = collectionViewLayout;
        
        return self;
    };
}
/** 注册集合视图页眉页脚（collectionView） */
- (MSChainMaker *(^)(id viewClass, NSString *elementKind, NSString *identifier))ms_registerSupplementaryViewClass
{
    return ^(id viewClass, NSString *elementKind, NSString *identifier) {
        
        AssertIsCollectionView
        [originalObj(UICollectionView) registerClass:viewClass forSupplementaryViewOfKind:elementKind withReuseIdentifier:identifier];
        
        return self;
    };
}


#pragma mark - alertController
/** 添加按钮（alertController） */
- (MSChainMaker * _Nonnull (^)(UIAlertAction *action))ms_addAction
{
    return ^(UIAlertAction *action) {
        
        AssertIsAlertController
        [originalObj(UIAlertController) addAction:action];
        
        return self;
    };
}
/** alert title字体和颜色 */
- (MSChainMaker * _Nonnull (^)(UIFont * _Nonnull, UIColor * _Nonnull))ms_titleFontAndColor
{
    return ^(UIFont *font, UIColor *color) {
        
        AssertIsAlertController
        NSMutableAttributedString *titleAtt = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"\n%@", originalObj(UIAlertController).title]];
        [titleAtt addAttributes:@{NSFontAttributeName : font,
                                  NSForegroundColorAttributeName : color}
                          range:NSMakeRange(0,
                                            titleAtt.length)];
        [originalObj(UIAlertAction) setValue:titleAtt
                                      forKey:@"attributedTitle"];
        
        return self;
    };
}
/** alert message字体和颜色 */
- (MSChainMaker * _Nonnull (^)(UIFont * _Nonnull, UIColor * _Nonnull, NSTextAlignment))ms_messageFontColorAndAlignment
{
    return ^(UIFont *font, UIColor *color, NSTextAlignment alignment) {
        
        AssertIsAlertController
        NSMutableAttributedString *messageAtt = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"\n%@", originalObj(UIAlertController).message]];
        NSMutableParagraphStyle *par = [[NSMutableParagraphStyle alloc] init];
        par.alignment = alignment;
        [messageAtt addAttributes:@{NSFontAttributeName : font,
                                    NSForegroundColorAttributeName : color,
                                    NSParagraphStyleAttributeName : par}
                            range:NSMakeRange(0,
                                              messageAtt.length)];
        [originalObj(UIAlertAction) setValue:messageAtt
                                      forKey:@"attributedMessage"];
        
        return self;
    };
}


#pragma mark - alertAction
/** 添加到alertController（alertAction） */
- (MSChainMaker * _Nonnull (^)(UIAlertController *alert))ms_addToAlert
{
    return ^(UIAlertController *alert) {
        
        AssertIsAlertAction
        [alert addAction:originalObj(UIAlertAction)];
        
        return self;
    };
}
/** alert 按钮文字颜色（alertAction） */
- (MSChainMaker * _Nonnull (^)(UIColor * _Nonnull))ms_titleTextColor
{
    return ^(UIColor *color) {
        
        AssertIsAlertAction
        [originalObj(UIAlertAction) setValue:color
                                         forKey:@"titleTextColor"];
        
        return self;
    };
}


#pragma mark - NSMutableAttributedString
/** 设置文字字体 */
- (MSChainMaker *(^)(UIFont *font, NSRange range))ms_fontAttribute
{
    return ^(UIFont *font, NSRange range) {
        
        AssertIsAttributedString
        [originalObj(NSMutableAttributedString) addAttribute:NSFontAttributeName value:font range:range];
        return self;
    };
}
/** 设置文字颜色 */
- (MSChainMaker *(^)(UIColor *color, NSRange range))ms_colorAttribute
{
    return ^(UIColor *color, NSRange range) {
        
        AssertIsAttributedString
        [originalObj(NSMutableAttributedString) addAttribute:NSForegroundColorAttributeName value:color range:range];
        return self;
    };
}
/** 设置字间距 */
- (MSChainMaker *(^)(NSNumber *Kern, NSRange range))ms_kernAttribute
{
    return ^(NSNumber *Kern, NSRange range) {
        
        AssertIsAttributedString
        [originalObj(NSMutableAttributedString) addAttribute:NSKernAttributeName value:Kern range:range];
        return self;
    };
}
/** 设置段落 */
- (MSChainMaker *(^)(NSTextAlignment alignment, CGFloat lineSpacing, NSLineBreakMode lineBreakMode, NSRange range))ms_paragraphStyleAttribute
{
    return ^(NSTextAlignment alignment, CGFloat lineSpacing, NSLineBreakMode lineBreakMode, NSRange range) {
        
        AssertIsAttributedString
        NSMutableParagraphStyle *par = [[NSMutableParagraphStyle alloc] init];
        par.lineSpacing = lineSpacing;
        par.alignment = alignment;
        par.lineBreakMode = lineBreakMode;
        [originalObj(NSMutableAttributedString) addAttribute:NSParagraphStyleAttributeName value:par range:range];
        return self;
    };
}
/** 设置删除线 */
- (MSChainMaker *(^)(UIColor *color, NSRange range))ms_strikethroughStyleAttribute
{
    return ^(UIColor *color, NSRange range) {
        
        AssertIsAttributedString
        [originalObj(NSMutableAttributedString) addAttributes:@{NSStrikethroughStyleAttributeName: [NSNumber numberWithInteger:NSUnderlineStyleSingle],
                                                                NSBaselineOffsetAttributeName : @0,
                                                                NSStrikethroughColorAttributeName : color}
                                                        range:range];
        return self;
    };
}


#pragma mark - private method
/** 贝塞尔曲线 */
- (CAShapeLayer *)ms_addLineOriginPoint:(CGPoint)p0
                                toPoint:(CGPoint)p1
                                  color:(UIColor *)color
                            borderWidth:(CGFloat)borderWidth
{
    
    /// 线的路径
    UIBezierPath *bezierPath = [UIBezierPath bezierPath];
    [bezierPath moveToPoint:p0];
    [bezierPath addLineToPoint:p1];
    
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.path = bezierPath.CGPath;
    shapeLayer.strokeColor = color.CGColor;
    shapeLayer.fillColor = [UIColor clearColor].CGColor;
    shapeLayer.lineWidth = borderWidth;
    
    return shapeLayer;
}

@end

UIView *ms_newView(void) {
    return [[UIView alloc] init];
}
UIScrollView *ms_newScrollView(void) {
    return [[UIScrollView alloc] init];
}
UIButton *ms_newButton(void) {
    return [UIButton buttonWithType:UIButtonTypeCustom];
}
UILabel *ms_newLabel(void) {
    return [[UILabel alloc] init];
}
UIImageView *ms_newImageView(void) {
    return [[UIImageView alloc] init];
}
UITableView *ms_newTableView(UITableViewStyle style) {
    return [[UITableView alloc] initWithFrame:CGRectZero style:style];
}
UICollectionView *ms_newCollectionView(UICollectionViewLayout *layout) {
    return [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
}
CAGradientLayer *ms_newGradientLayer(void) {
    return [[CAGradientLayer alloc] init];
}
